#include "print.hpp"
using std::cout;
using std::endl;

// Print vector<T>.
template<typename T> ostream& operator <<(ostream& out, const vector<T> & vec)
{
  unsigned int i;
  out << "[";
  for(i=0; i<vec.size(); i++)
    {
      out << vec[i];
      if(i < vec.size() - 1)
	out << ", ";
    }
  out << "]";
  return out;
}

template ostream& operator <<(ostream& os, const vector<int> & vec);
template ostream& operator <<(ostream& os, const vector<string> & vec);

// Print vector<T>.
template<typename S, typename T> ostream& operator <<(ostream& out, const map<S, T>& m)
{
  typename map<S, T>::const_iterator pos;
  size_t i;
  out << "{";
  for(i=0, pos = m.begin(); i< m.size() && pos != m.end(); i++, pos++)
    {
      out << pos->first << ":" << pos->second;
      if(i < m.size() - 1)
	 out << ", ";
    }
  out << "}";
  return out;
}

template ostream& operator <<(ostream& out, const map<string, int>& m);

// Return string value of vector<T>.
template<typename T> string stringval(const vector<T>& vec)
{
  std::stringstream buffer;
  //return "[" + p.first + "," + buffer.str() + "]";

  unsigned int i;
  buffer << "[";
  for(i=0; i<vec.size(); i++)
    {
      buffer << vec[i];
      if(i < vec.size() - 1)
	buffer << ",";
    }
  buffer << "]";
  return buffer.str();
}

// Print string value of pair<S, T>
template<typename S, typename T> string stringval(const std::pair<S, T>& p)
{
  std::stringstream buffer;
  buffer << p.second;
  return "[" + p.first + "," + buffer.str() + "]";
}


// Print pair<S, T>
template<typename S, typename T> void print(const std::pair<S, T>& p)
{
  cout << "[";
  cout << p.first;
  cout << ",";
  cout << p.second;
  cout << "]" << endl;
}

// Print set<T>.
template<typename T> ostream& operator <<(ostream& out, const set<T> & s)
{
  typename set<T>::iterator pos;
  out << "[";
  for(pos=s.begin(); pos != s.end(); pos++)
    {
      out << *pos;
      if(pos != --s.end())
	out << ",";
    }
  out << "]" << endl;
  return out;
}

template ostream& operator <<(ostream& out, const set<string> & s);

// Return value of boost::array<T, dim> as string.
template<typename T, int dim> string stringval(const boost::array<T, dim>& arr)
{
  std::stringstream buffer;
  unsigned int i;
  buffer << "[";
  for(i=0; i<dim; i++)
    {
      buffer << arr[i];
      if(i < dim - 1)
        buffer << ",";
    }
  buffer << "]";
  return buffer.str();
}

// // Print boost::array<T, dim>.
// template<typename T, int dim> void print(const boost::array<T, dim>& arr)
// {
//   unsigned int i;
//   cout << "[";
//   for(i=0; i<dim; i++)
//     {
//       cout << arr[i];
//       if(i < dim - 1)
//         cout << ",";
//     }
//   cout << "]" << endl;
// }

//template void print<string, 2>(const boost::array<string, 2>& arr);
//template void print<string, 3>(const boost::array<string, 3>& arr);

// Print boost::array<T, dim>.
//template<typename T, int dim> void print(const boost::array<T, dim>& arr)
template<typename T, int dim> ostream& operator <<(ostream& out, const boost::array<T, dim> & arr)
{
  unsigned int i;
  out << "[";
  for(i=0; i<dim; i++)
    {
      out << arr[i];
      if(i < dim - 1)
        out << ",";
    }
  out << "]";
  return out;
}

template ostream& operator <<<string, 2>(ostream& out, const boost::array<string, 2> & arr);
template ostream& operator <<<string, 3>(ostream& out, const boost::array<string, 3> & arr);

// template<typename T, int dim> void print(const vector<boost::array<T, dim> >& lst)
// {
//   typename list<boost::array<T, dim> >::const_iterator pos;
//   cout << "[";
//   for(pos=lst.begin(); pos != lst.end(); pos++)
//     {
//       cout << stringval<T, dim>(*pos);
//       if(pos != --lst.end())
//         cout << ",";
//     }
//   cout << "]" << endl;
// }

template<typename T, int dim> ostream& operator <<(ostream& out, const vector<boost::array<T, dim> >& lst)
{
  typename vector<boost::array<T, dim> >::const_iterator pos;
  out << "[";
  for(pos=lst.begin(); pos != lst.end(); pos++)
    {
      out << stringval<T, dim>(*pos);
      if(pos != --lst.end())
        out << ",";
    }
  out << "]";
  return out;
}

//template ostream& operator <<<string, 3>(ostream& out, const vector<boost::array<string, 3> >& lst);

